/////////////////////////////////////////////////////////////////////////////
// Copyright(c) 2012-2015 purang All Rights Reserved
// Name:        buffer_wrapper.h
// Purpose:
// Author:      syy
// Modified by:
// Created:     2014/9/2 16:27
// RCS-ID:
// Licence:
/////////////////////////////////////////////////////////////////////////////
#ifndef _BUFFER_WRAPPER_H_
#define _BUFFER_WRAPPER_H_
#include <string.h>

#include <vector>

#include "core/system/critical_section_wrapper.h"

namespace qb {

inline void __memcpy(void *pDst, uint32_t dwDstSize, void *pScr,
                     uint32_t dwCpSize) {
#ifdef _MSC_VER
  memcpy_s(pDst, dwDstSize, pScr, dwCpSize);
#else
  memcpy(pDst, pScr, dwCpSize > dwDstSize ? dwDstSize : dwCpSize);
#endif
}

#define bcopy(s, d, ss) __memcpy(d, ss, (void *)s, ss)
const uint32_t trunkSize = 64 * 1024;

template <typename _type>
class CBufferWrapper {
 public:
  CBufferWrapper()
      : _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
        _maxSize(0),
        _offPtr(0),
        _currPtr(0) {}

  virtual ~CBufferWrapper() { delete &_critSect; }

  inline void enter() { _critSect.Enter(); }

  inline void leave() { _critSect.Leave(); }

  inline void put(const char *buf, const uint32_t size) {
    wr_reserve(size);
    bcopy(buf, &_buffer[_currPtr], size);
    _currPtr += size;
  }

  inline char *wr_buf() { return &_buffer[_currPtr]; }

  inline char *rd_buf() { return &_buffer[_offPtr]; }

  inline bool rd_ready() {
    bool ret = _currPtr > _offPtr;
    return ret;
  }

  inline uint32_t rd_size() {
    uint32_t ret = _currPtr - _offPtr;
    return ret;
  }

  inline void rd_flip(uint32_t size) {
    if (size == 0) {
      return;
    }
    _offPtr += size;
    if (_currPtr > _offPtr) {
      uint32_t tmp = _currPtr - _offPtr;
      if (_offPtr >= tmp) {
        memmove(&_buffer[0], &_buffer[_offPtr], tmp);
        _offPtr = 0;
        _currPtr = tmp;
      }
    } else {
      _offPtr = 0;
      _currPtr = 0;
    }
  }

  inline uint32_t wr_size() {
    uint32_t ret = _maxSize - _currPtr;
    return ret;
  }

  inline void wr_flip(const uint32_t size) { _currPtr += size; }

  inline void reset() {
    _offPtr = 0;
    _currPtr = 0;
  }

  inline uint32_t maxSize() const { return _maxSize; }

  inline void wr_reserve(const uint32_t size);

 private:
  CriticalSectionWrapper &_critSect;
  uint32_t _maxSize;
  uint32_t _offPtr;
  uint32_t _currPtr;
  _type _buffer;
};

typedef CBufferWrapper<std::vector<char> > BufferQueue;

template <>
inline void BufferQueue::wr_reserve(const uint32_t size) {
  if (wr_size() < size) {
#define trunkCount(size) (((size) + trunkSize - 1) / trunkSize)
    _maxSize += (trunkSize * trunkCount(size));
    _buffer.resize(_maxSize);
  }
}

}  // namespace qb

#endif  // _BUFFER_WRAPPER_H_
